/**
 * Copyright 2011 Honeywell Federal Manufacturing & Technologies, LLC. This material was produced under U.S. Government
 * contract DE-ACO4-01AL66850, Honeywell Federal Manufacturing & Technologies, LLC, (FM&T) with the U. S. Department of
 * Energy for the operation of the Kansas City Plant . The U.S. Government has rights to use, reproduce, and distribute
 * this software.  NEITHER THE GOVERNMENT NOR Honeywell Federal Manufacturing & Technologies, LLC, MAKES ANY WARRANTY,
 * EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified to produce
 * derivative works, such modified software should be clearly marked, so as not to confuse it with the version available
 * from FM&T.
 *
 * Additionally, this program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License Version 3 published by the Free Software Foundation. Accordingly, this program is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this library.
 * If not, see http://www.gnu.org/licenses/.
 */
package org.braintrain.tapestry.view.components;

import com.javaforge.tapestry.spring.annotations.InjectSpring;
import com.kcp.ko.fmtnmlib.service.HibernatePersistenceService;
import org.apache.log4j.Logger;
import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.annotations.*;
import org.apache.tapestry.services.DataSqueezer;
import org.braintrain.domain.*;
import org.braintrain.domain.types.ModuleNumbering;
import org.braintrain.domain.types.NavigationType;
import org.braintrain.domain.types.ResourceType;
import org.braintrain.services.ContentService;
import org.braintrain.services.DeltaResourceManager;
import org.braintrain.services.MediaService;
import org.braintrain.services.NavigationService;
import org.braintrain.tapestry.aso.TestASO;
import org.braintrain.tapestry.view.*;

import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


public abstract class NavigationBorder extends BaseComponent {

    private static final Logger LOG = Logger.getLogger(NavigationBorder.class);
    
    @Asset("/images/edit.gif")
    public abstract IAsset getEditImage(); 
    
    @Asset("/images/nextgradient.gif")
    public abstract IAsset getNextImage(); 
    
    @Asset("/images/backgradient.gif")
    public abstract IAsset getBackImage(); 
    
    @Asset("/images/returngradient.gif")
    public abstract IAsset getReturnImage(); 
    
    @Asset("/images/backgradientdisabled.gif")
    public abstract IAsset getBackDisabledImage(); 
    
    @Asset("/images/nextgradientdisabled.gif")
    public abstract IAsset getNextDisabledImage();
    
    @Asset("/images/home.gif")
    public abstract IAsset getHomeImage(); 
    
    @InjectState("testaso")
    public abstract TestASO getTestASO();
    
    //Page Injections
    @InjectPage("View")
    public abstract View getViewPage();
    
    @InjectPage("Test")
    public abstract Test getTestPage();
    
    @InjectPage("EditTest")
    public abstract EditTest getEditTestPage();
    
    @InjectPage("ModuleAdmin")
    public abstract ModuleAdmin getModuleAdminPage();
    
    @InjectPage("Home")
    public abstract Home getHomePage();
    
    @InjectPage("Evaluation")
    public abstract Evaluation getEvaluationPage();
    
    @InjectSpring("navigationService")
    public abstract NavigationService getNavigationService();
    
    @InjectSpring("genericHibernateService")
    public abstract HibernatePersistenceService getGenericService();
    
    @InjectSpring("mediaService")
    public abstract MediaService getMediaService();
    
    @InjectSpring("contentService")
    public abstract ContentService getContentService();

    @InjectSpring("resourceManager")
    public abstract DeltaResourceManager getResourceManager();
    
    @InjectObject("service:tapestry.data.DataSqueezer")
    public abstract DataSqueezer getDataSqueezer();
    
    @Persist("session:page")
    public abstract boolean getEditHeader();
    public abstract void setEditHeader(boolean s);
    
    @Persist("session:page")
    public abstract boolean getEditFooter();
    public abstract void setEditFooter(boolean s);
    
    @Parameter(required=true)
    public abstract Navigation getNavigation();
    public abstract void setNavigation(Navigation nav);
    
    @Parameter(required=true)
    public abstract Long getNavigationId();
    public abstract void setNavigationId(Long nav);
    
    @Parameter(required=true)
    public abstract boolean getEditNavigation();
    public abstract void setEditNavigation(boolean edit);
    
    @Parameter(required=true)
    public abstract Navigation getParentNavigation();
    public abstract void setParentNavigation(Navigation nav);
    
    @Parameter(required=true)
    public abstract Long getParentNavigationId();
    public abstract void setParentNavigationId(Long nav);
    
    @Parameter(required=true)
    public abstract boolean isCmStaff();
    public abstract void setCmStaff(boolean admin);
    
    @Parameter(required=true)
    public abstract boolean isContentCreator();
    public abstract void setContentCreator(boolean admin);
    
    @Parameter(required=true)
    public abstract boolean isDeltaNavigation();
    public abstract void setDeltaNavigation(boolean admin);
    
    @Parameter(required=false, defaultValue="true")
    public abstract boolean isNextButtonEnabled();
    public abstract void setNextButtonEnabled(boolean enable);
    
    public abstract String getCurrentEditedHeader();
    public abstract void setCurrentEditedHeader(String c);
    
    public abstract String getCurrentEditedFooter();
    public abstract void setCurrentEditedFooter(String c);
        
    public void cancelSubmit(IRequestCycle cycle)
    {
        setEditHeader(false);
        setEditFooter(false);
        setEditNavigation(false);
    }
    
    public String generateNavigationTitle()
    {
        StringBuffer buff = new StringBuffer();
        
        buff.append(getNavigation().getModule().getNullSafeName().getRelevantValue(isDeltaNavigation()));
        
        buff.append(" : ");

        String name = getNavigation().getContent(isDeltaNavigation()).getName();
        if(name != null)
            buff.append(name);
        
        return buff.toString();
    }

    //View Header getter/Setter
    public void setHeader(String header)
    {
        setCurrentEditedHeader(header);
    }
    
    //get the navigation (regular or delta)
    public Navigation getPrevNavigation()
    {
        return getNavigation().getNullSafeBundle().getRelevantPrev(isDeltaNavigation());
    }
    
    public Navigation getNextNavigation()
    {
        return getNavigation().getNullSafeBundle().getRelevantNext(isDeltaNavigation());
    }
    
    //get the next/prev page types (regular or delta
    public String getPrevPageType()
    {
        Navigation prev = getPrevNavigation();
        Navigation parent = getParentNavigation();
        if(prev != null)
        {
            return prev.getType().name();
        }
        else if(parent != null)
        {
            return parent.getType().name();
        }
        
        return "Home";
    }
    
    public String getNextPageType()
    {
        Navigation next = getNextNavigation();
        Navigation parent = getParentNavigation();
        if(next != null)
        {
            return next.getType().name();
        }
        else if(parent != null)
        {
            return parent.getType().name();
        }
        else if(!getNavigation().isMainNavigation() && (isCmStaff() || isContentCreator()))
        {
            return ModuleAdmin.ExternalName;
        }
        
        return Evaluation.ExternalName;
    }
    
    //filter the correct next image to show (this is the only one that changes)
    public IAsset getNextImageFiltered()
    {
        if(!isNextButtonEnabled())
        {
            return getNextDisabledImage();
        }
        if(getNextNavigation() != null)
        {
            return getNextImage();
        }
        else if(getParentNavigation() != null)
        {
            return getReturnImage();
        }
        return getNextImage();
    }
    
    //convienience function for grabbing the id from a navigation
    public Long nullCheckNavId(Navigation nav)
    {
        if(nav != null)
        {
            return nav.getId();
        }
        return null;
    }
    
    public String getHeader()
    {
        return getResourceManager().getResourceValue(getNavigation().getModule().getHeader(), isDeltaNavigation());
    }

    //View Footer getter/Setter
    public void setFooter(String footer)
    {
        setCurrentEditedFooter(footer);
    }
    
    public String getFooter()
    {
        return getResourceManager().getResourceValue(getNavigation().getModule().getFooter(), isDeltaNavigation());
    }
    
    public synchronized void saveHeaderSubmit(IRequestCycle cycle)
    {
        Module module = getNavigation().getModule();
        if(module.getHeader() == null){
        	module.setHeader(new DeltaResource());
        }

        if(module.getHeader().getDeltaValue() == null){
            module.getHeader().setDeltaValue(new ResourceFacade(ResourceType.Content));
        }

        String headerContent = getContentService().parseHTMLBlobFile(getCurrentEditedHeader(), module.getHeader().getDeltaValue(), getNavigationId(), false, false, getDataSqueezer());
        getResourceManager().saveResourceValue(headerContent, module.getHeader());

        resetEdits();

    }
    
    public synchronized void saveFooterSubmit(IRequestCycle cycle)
    {
        Module module = getNavigation().getModule();
        if(module.getFooter() == null){
        	module.setFooter(new DeltaResource());
        }

        if(module.getFooter().getDeltaValue() == null){
            module.getFooter().setDeltaValue(new ResourceFacade(ResourceType.Content));
        }

        String footerContent = getContentService().parseHTMLBlobFile(getCurrentEditedFooter(), module.getFooter().getDeltaValue(), getNavigationId(), false, false, getDataSqueezer());
        getResourceManager().saveResourceValue(footerContent, module.getFooter());

        resetEdits();
    }

    public void resetEdits(){
        setEditHeader(false);
        setEditFooter(false);
        setEditNavigation(false);
    }
    
    //  moduleHome
    public void moduleHome(IRequestCycle cycle, Long moduleId)
    {
        getModuleAdminPage().activate(cycle, moduleId);
    }
    
    //Add a page next
    public void addPageNext(IRequestCycle cycle, Long navId)
    {
        setNavigationId(navId);
        getViewPage().setEditContent(true);
        getViewPage().activate(cycle, addNavigationNext(getNavigation(), new Content()).getId(), nullCheckNavId(getParentNavigation()));
    }
    
    //Add a test
    public void addTestNext(IRequestCycle cycle, Long navId)
    {
        setNavigationId(navId);
        getEditTestPage().activate(cycle, addNavigationNext(getNavigation(), new TestData()).getId(), nullCheckNavId(getParentNavigation()));
    }
    
    //delete the current navigation
    public void deleteCurrent(IRequestCycle cycle, Long navId)
    {
        setNavigationId(navId);
        
        Long moduleId = getNavigation().getModule().getId();
        
        getNavigationService().deleteNavigation(getNavigation().getId());
        
        getModuleAdminPage().activate(cycle, moduleId);
    }
    
    private Navigation addNavigationNext(Navigation current, ContentBase content)
    {
        //link up to the current module
        Navigation nav = new Navigation();
        
        nav.getNullSafeContent().setDeltaValue(content);
        nav.setType(content.getType());
        
        if(current.isMainNavigation())
        {
            current.getModule().getMainPages().add(nav);
        }
        else
        {
            current.getModule().getLinkPages().add(nav);
        }
        
        nav.setModule(current.getModule());
        nav.setMainNavigation(current.isMainNavigation());
        
        return getNavigationService().insertNavigation(current, nav);
    }
    
    public boolean getInsertPageNumber()
    {
        return getNavigation().getModule().getNumbering() != ModuleNumbering.None  &&
        getNavigation().getModule().isActive() &&
        getNavigation().isMainNavigation() &&
        getNavigation().getNavIndex() != null;
    }
    
    public void editHeaderSubmit(IRequestCycle cycle)
    {
        setEditHeader(true);
        setEditFooter(false);
        setEditNavigation(false);
        editContentSubmit(cycle);
    }
    
    public void editFooterSubmit(IRequestCycle cycle)
    {
        setEditFooter(true);
        setEditHeader(false);
        setEditNavigation(false);
        editContentSubmit(cycle);
    }
    
    public void editContentSubmit(IRequestCycle cycle)
    {
        Object[] params = cycle.getListenerParameters();
        if(params != null && params.length > 0 && params[0] instanceof Long)
        {
            setNavigationId((Long)params[0]);
            if(params.length > 1 && params[1] instanceof Long)
            {
                setParentNavigationId((Long)params[1]);
            }
        }
    }
    
    public String getNavigationStatus()
    {
        return getNavigation().getStatusString();
    }
    
    protected String blobFileToString(BlobFile blob)
    {
        StringBuffer buff = new StringBuffer();
        
        InputStreamReader reader = null;
        try {
            if(blob != null && blob.getData() != null)
            {
                reader = new InputStreamReader(blob.getData().getBinaryStream());
            
                char[] buf = new char[256];
                int i = 0;
                
                while((i = reader.read(buf)) > 0)
                {
                    buff.append(buf,0,i);
                }

            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    LOG.error("Error closing reader and stream", e);
                }
            }
        }
        return buff.toString();
    }    
    
    public void rollBackNavigation(IRequestCycle cycle, Long navId)
    {
        setNavigationId(navId);
        
        getNavigationService().saveRollBackDeltaNavigation(navId);
        
        if(getNavigation().getType() == NavigationType.Test)
        {
            getTestASO().clear();
            getTestPage().activate(cycle, getNavigation().getId(), nullCheckNavId(getParentNavigation()));
        }
        else if(getNavigation().getType() == NavigationType.View)
        {
            getViewPage().activate(cycle, getNavigation().getId(), nullCheckNavId(getParentNavigation()));
        }
    }
    
    public boolean isNavigationDeleted()
    {
        return getNavigation().isDeleted();
    }
    
    public void undeleteNavigation(IRequestCycle cycle, Long navId)
    {
        setNavigationId(navId);
        getNavigationService().saveUndeleteNavigation(navId);
    }
    
    /*public String generateCurrentPagePath(){
        return ContentServiceEncoder.buildPagePath(getNavigation().getType(),getDataSqueezer().squeeze(new Long[]{getNavigation().getId(),getNavigation().getModule().getId()}));
    }*/
    
    public List getNextPageParameters()//{nullCheckNavId(nextNavigation), nullCheckNavId(parentNavigation)}
    {
        List<Long> parameters = new ArrayList<Long>();
        String nextPageType = getNextPageType();
        if(nextPageType.equals(ModuleAdmin.ExternalName))
        {
            parameters.add(getNavigation().getModule().getId());
        }
        else if(nextPageType.equals(Evaluation.ExternalName)){
            parameters.add(getNavigation().getModule().getId());
        }
        else {
            parameters.add(nullCheckNavId(getNextNavigation()));
            parameters.add(nullCheckNavId(getParentNavigation()));
        }
        
        return parameters;
    }
    
    //{nullCheckNavId(prevNavigation), nullCheckNavId(parentNavigation)}
    public List getPrevPageParameters()//{nullCheckNavId(nextNavigation), nullCheckNavId(parentNavigation)}
    {
        List<Long> parameters = new ArrayList<Long>();
        
        parameters.add(nullCheckNavId(getPrevNavigation()));
        parameters.add(nullCheckNavId(getParentNavigation()));
        
        return parameters;
    }
    
    public boolean getPageIsntLinkedTo()
    {
        return getNavigation().getReferences().size() == 0;
    }

    public TinyMCEConfigurationFactory getConfigurationFactory(){
        return new TinyMCEConfigurationFactory();
    }
}